/*
 * Copyright 2013 
 *
 * 
 */
package com.staples.copyprint.webservice.service;

import java.io.ByteArrayInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;

import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.log4j.Logger;
import org.jdom2.Attribute;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.DOMBuilder;
import org.jdom2.xpath.XPath;
import org.springframework.stereotype.Service;
import org.xml.sax.InputSource;

import com.staples.copyprint.webservice.domain.VendorProduct;
import com.staples.copyprint.webservice.domain.VendorTemplateSkus;
import com.staples.copyprint.webservice.endpoint.CreateEfiXmlEndPoint;
import com.staples.copyprint.webservice.repository.VendorProductRepository;
import com.staples.copyprint.webservice.util.EFIResourceBundle;
import com.staples.copyprint.webservice.util.Util;
/**
 *   
 * Class Name - createEfiXmlServiceImpl 
 * 
 * This class implements createEfiXmlService interface
 * This is responsible for canonical xml parsing 
 * and population of EFI xml
 */
@Service
@SuppressWarnings("deprecation")
public class CreateEfiXmlServiceImpl implements CreateEfiXmlService {

	private static final Logger logger = Logger.getLogger(CreateEfiXmlEndPoint.class);
	
	@Resource
	private VendorProductRepository vendorProductRepository;
	ResourceBundle efiBundle = EFIResourceBundle.getEFIResourceProperties();
	ResourceBundle canonicalBundle = EFIResourceBundle.getCanonicalXPathProperties();
	ResourceBundle fixedDataBundle = EFIResourceBundle.getFixedDataMappingProperties();
	
	/**
	 * This method get values from canonical xml nodes
	 * @param canonicalXML
	 * @throws InsufficientConfigurationException
	 */
	public Element createEfiXml(Element canonicalXML) throws InsufficientConfigurationException {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createEfiXml()");
		logger.debug("----->Input Parameter of createEfiXml: "+canonicalXML);
		
		Element doc = canonicalXML;
		String orderNumber=null;
		String reason=null;
		try {
			Element root = doc.getDocument().getRootElement();
			String vendor = null;

			// GET Vendor
			XPath vendorPath = XPath.newInstance(efiBundle.getString("vendorPath"));
			Element vendorElement = (Element) vendorPath.selectSingleNode(root);
			if(vendorElement == null){
				throw new Exception("Location/Id "+efiBundle.getString("NullPointerErrorMessage"));
			} else {
				vendor = vendorElement.getValue();
			}
			logger.info("-----> vendor:"+vendor);
			
			XPath vendorheaderNumberPath= XPath.newInstance(efiBundle.getString("vendorheaderNumberPath"));
			Element vendorheaderNumberElement = (Element) vendorheaderNumberPath.selectSingleNode(root);
			
			Attribute vendorOrderAtb = (Attribute) XPath.newInstance(canonicalBundle.getString("Customer.Id_Original")).selectSingleNode(root);
			if(vendorOrderAtb == null){
				throw new Exception("CustomerId>Original "+efiBundle.getString("NullPointerErrorMessage"));
			}
			
			if(vendorheaderNumberElement == null){
				throw new Exception("Order number "+efiBundle.getString("NullPointerErrorMessage"));
			} else {
				orderNumber=vendorheaderNumberElement.getValue().trim();
				if(orderNumber.equals(null)||orderNumber.equals("")){
					orderNumber="No order number";
					throw new Exception("No order number found.");
				} else {
					orderNumber = orderNumber+", Vendor Order#: "+vendorOrderAtb.getValue();
				}
			}
			logger.info("-----> vendorheaderNumberElement:"+vendorheaderNumberElement.getValue());
			
			//MAKE EFI XML
			Element responseDoc = createEFIXMLMetaData();
			Element responseRoot = responseDoc.getDocument().getRootElement();
			Element canonicalRoot = doc.getDocument().getRootElement();
			
			createBuyerUser(responseRoot,canonicalRoot);
			
			createBuyerAddress(responseRoot,canonicalRoot);
			
			createGeneralOrderInfo(responseRoot,canonicalRoot);
			
			createPaymentMethodAndPaymentAddress(responseRoot,canonicalRoot);
			
			createOrderInfo(responseRoot,canonicalRoot);
			
			createOrderLevelTotalAndTax(responseRoot,canonicalRoot);
			
			// GET PRODUCT ID AND Product
			XPath vendorLinePath = XPath.newInstance(efiBundle.getString("lineNodePath"));
			List<Element> lines =(List<Element>) vendorLinePath.selectNodes(root);
			
			parseLineLevelDataAndPopulateEFI(vendor, lines, responseRoot, canonicalRoot);
			
			logger.info("Leaving CreateEfiXmlServiceImpl.createEfiXml()");
			
			return responseDoc;

		} 
		catch (Exception e) {

			logger.error("Exception in CreateEfiXmlServiceImpl:",e);
			if(reason==null){
				reason=e.getMessage();
			}
			
			// TRIGGER EMAIL
			Util.mailTrigger(reason, orderNumber,null);
			throw new InsufficientConfigurationException("",efiBundle.getString("FAULT_STRING")+orderNumber+". \n Reason: "+reason);
			
		}	
			
	}
	
	/**
	 * createEFIXMLMetaData
	 * 
	 * This method is responsible for
	 * loading of EFI template xml and population 
	 * of version info
	 * */	
	private Element createEFIXMLMetaData() throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createEFIXMLMetaData()");
		
		Element doc= null;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();   
        DocumentBuilder builder;   

		builder = factory.newDocumentBuilder();
		org.w3c.dom.Document document = builder.parse( getClass().getResourceAsStream("/META-INF/one.xml")) ;
		doc = new DOMBuilder().build(document.getDocumentElement());
		Element root = doc.getDocument().getRootElement();
		
		XPath majorVer = XPath.newInstance(efiBundle.getString("SchemaVersion.MajorVersion"));
		Element majorVerElement = (Element) majorVer.selectSingleNode(root);
		majorVerElement.setText( fixedDataBundle.getString("SchemaVersion.MajorVersion") );
		
		XPath minorVer = XPath.newInstance(efiBundle.getString("SchemaVersion.MinorVersion"));
		Element minorVerElement = (Element) minorVer.selectSingleNode(root);
		minorVerElement.setText( fixedDataBundle.getString("SchemaVersion.MinorVersion") );
		
		Element csClassElement = (Element) XPath.newInstance(efiBundle.getString("CreationSoftware.Classification")).selectSingleNode(root);
		csClassElement.setText( fixedDataBundle.getString("CreationSoftware.Classification") );
		
		Element csDescElement = (Element) XPath.newInstance(efiBundle.getString("CreationSoftware.Description")).selectSingleNode(root);
		csDescElement.setText( fixedDataBundle.getString("CreationSoftware.Description") );
		
		Element csVersionElement = (Element) XPath.newInstance(efiBundle.getString("CreationSoftware.VersionNumbers")).selectSingleNode(root);
		Element csMajVer = (Element) XPath.newInstance("//s1:VersionNumber").selectSingleNode(csVersionElement);
		csMajVer.setText(fixedDataBundle.getString("CreationSoftware.VersionNumbers.MajVer"));
		csVersionElement.addContent(new Element("VersionNumber","s1","com.printcafe.printersiteinternal").setText(fixedDataBundle.getString("CreationSoftware.VersionNumbers.MinVer")));
		csVersionElement.addContent(new Element("VersionNumber","s1","com.printcafe.printersiteinternal").setText(fixedDataBundle.getString("CreationSoftware.VersionNumbers.SoftRelease1")));
		csVersionElement.addContent(new Element("VersionNumber","s1","com.printcafe.printersiteinternal").setText(fixedDataBundle.getString("CreationSoftware.VersionNumbers.SoftRelease2")));
			
		logger.info("Leaving CreateEfiXmlServiceImpl.createEFIXMLMetaData()");
		return doc;
	}
	
	
	/**
	 * createGeneralOrderInfo
	 * 
	 * @param efiRootNode
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of general info like currency code, store no 
	 * 
	 * */
	private void createGeneralOrderInfo(Element root, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createGeneralOrderInfo()");
		Element dueDateUtcElement = (Element) XPath.newInstance(efiBundle.getString("RequestedDueDateUtc")).selectSingleNode(root);
		Element dueDateUtcValElement = (Element) XPath.newInstance(canonicalBundle.getString("GeneralOrderInfo.RequestedDueDateUtc")).selectSingleNode(canonicalRoot);
		if(dueDateUtcValElement == null){
			throw new Exception("RequestedDelivery Date "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			dueDateUtcElement.setText( dueDateUtcValElement.getValue() );
		}
		
		Element currencyCodeElement = (Element) XPath.newInstance(efiBundle.getString("CurrencyCode")).selectSingleNode(root);
		Element currencyCodeValElement = (Element) XPath.newInstance(canonicalBundle.getString("GeneralOrderInfo.CurrencyCode")).selectSingleNode(canonicalRoot);
		if(currencyCodeValElement == null){
			throw new Exception("CurrencyCode "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			currencyCodeElement.setText( currencyCodeValElement.getValue() );
		}
		
		Element facilityElement = (Element) XPath.newInstance(efiBundle.getString("Facility")).selectSingleNode(root);
		Element facilityValElement = (Element) XPath.newInstance(canonicalBundle.getString("GeneralOrderInfo.Facility")).selectSingleNode(canonicalRoot);
		if(facilityValElement == null){
			throw new Exception("Store Nmb "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			facilityElement.getAttribute("CommonFacilityIdentifier").setValue(facilityValElement.getValue() );
		}
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createGeneralOrderInfo()");
		
	}
	
	
	/**
	 * createBuyerCompanyData
	 * 
	 * @param efiRootNode
	 * @param VendorProduct
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of Buyer company info 
	 * 
	 * */
	private void createBuyerCompanyData(Element root, VendorProduct vp) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createBuyerCompanyData()");
		
		Element buyerCompIdElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Company.IdData.DSF.Id")).selectSingleNode(root);
		if(vp != null && (vp.getVendorCompanyId() != null || vp.getVendorCompanyId() != "") ) {
			buyerCompIdElement.setText( vp.getVendorCompanyId() );
		} else {
			buyerCompIdElement.setText( "" );
		}
		
		Element buyerCompIdTypeElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Company.IdData.DSF.IdTypeName")).selectSingleNode(root);
		buyerCompIdTypeElement.setText( fixedDataBundle.getString("Buyer.Company.IdData.DSF.IdTypeName") );
		
		Element buyerCompDescElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Company.IdData.DSF.Description")).selectSingleNode(root);
		buyerCompDescElement.setText( fixedDataBundle.getString("Buyer.Company.IdData.DSF.Description") );
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createBuyerCompanyData()");
		
	}
	
	/**
	 * createBuyerUser
	 * 
	 * @param efiRootNode
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of Buyer user info in EFI xml
	 * 
	 * */
	private void createBuyerUser(Element root, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createBuyerUser()");
	
		Element buyerUserIdElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.User.IdData.External.Id")).selectSingleNode(root);
		buyerUserIdElement.setText( "" );
		
		Element buyerUserIdTypeElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.User.IdData.External.IdTypeName")).selectSingleNode(root);
		buyerUserIdTypeElement.setText( fixedDataBundle.getString("Buyer.User.IdData.External.IdTypeName") );
		
		Element buyerUserDescElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.User.IdData.External.Description")).selectSingleNode(root);
		if( buyerUserDescElement !=null )buyerUserDescElement.setText( fixedDataBundle.getString("Buyer.User.IdData.External.Description") );
		
		Element buyerUserFnameElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.User.NameComponents.First")).selectSingleNode(root);
		Element buyerUserFnameValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.User.NameComponents.First")).selectSingleNode(canonicalRoot);
		if(buyerUserFnameValElement == null){
			throw new Exception("FirstName "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerUserFnameElement.setText( buyerUserFnameValElement.getValue() );
		}
		
		Element buyerUserLnameElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.User.NameComponents.Last")).selectSingleNode(root);
		Element buyerUserLnameValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.User.NameComponents.Last")).selectSingleNode(canonicalRoot);
		if(buyerUserLnameValElement == null){
			throw new Exception("LastName "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerUserLnameElement.setText( buyerUserLnameValElement.getValue() );
		}
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createBuyerUser()");
		
	}
	
	
	/**
	 * createBuyerAddress
	 * 
	 * @param efiRootNode
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of Buyer address info in EFI xml
	 * 
	 * */
	private void createBuyerAddress(Element root, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createBuyerAddress()");
	
		Element buyerAddFnameElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.NameFirst")).selectSingleNode(root);
		Element buyerAddFnameValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.User.NameComponents.First")).selectSingleNode(canonicalRoot);
		if(buyerAddFnameValElement == null){
			throw new Exception("FirstName "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerAddFnameElement.setText( buyerAddFnameValElement.getValue() );
		}
		
		Element buyerAddLnameElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.NameLast")).selectSingleNode(root);
		Element buyerAddLnameValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.User.NameComponents.Last")).selectSingleNode(canonicalRoot);
		if(buyerAddLnameValElement == null){
			throw new Exception("LastName "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerAddLnameElement.setText( buyerAddLnameValElement.getValue() );
		}
		
		Element buyerAddressElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.Address1")).selectSingleNode(root);
		Element buyerAddressValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.Address1")).selectSingleNode(canonicalRoot);
		if(buyerAddressValElement == null){
			throw new Exception("AddressLine1 "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerAddressElement.setText( buyerAddressValElement.getValue() );
		}
		
		Element buyerAddCityElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.City")).selectSingleNode(root);
		Element buyerAddCityValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.City")).selectSingleNode(canonicalRoot);
		if(buyerAddCityValElement == null){
			throw new Exception("City "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerAddCityElement.setText( buyerAddCityValElement.getValue() );
		}
		
		Element buyerAddStateElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.State_Province_Region")).selectSingleNode(root);
		Element buyerAddStateValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.State_Province_Region")).selectSingleNode(canonicalRoot);
		if(buyerAddStateValElement == null){
			throw new Exception("State "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerAddStateElement.setText( buyerAddStateValElement.getValue() );
		}
		
		Element buyerAddZipElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.Zip_PostalCode")).selectSingleNode(root);
		Element buyerAddZipValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.Zip_PostalCode")).selectSingleNode(canonicalRoot);
		if(buyerAddZipValElement == null){
			throw new Exception("PostalCode "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			buyerAddZipElement.setText( buyerAddZipValElement.getValue() );
		}
		
		Element buyerAddCountryElement = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.Country")).selectSingleNode(root);
		/*Element buyerAddCountryValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.Country")).selectSingleNode(canonicalRoot);
		if(buyerAddCountryValElement == null){
			throw new Exception("Country "+efiBundle.getString("NullPointerErrorMessage"));
		} else {*/
			buyerAddCountryElement.setText( "US" );
		/*}*/
		
		Element buyerAddPhone1Element = (Element) XPath.newInstance(efiBundle.getString("Buyer.Address.Phone1")).selectSingleNode(root);
		Element buyerAddPhone1ValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.Phone1")).selectSingleNode(canonicalRoot);
		if(buyerAddPhone1ValElement == null){
			throw new Exception("PhoneList Number "+efiBundle.getString("NullPointerErrorMessage"));
		}else{
			if(buyerAddPhone1ValElement.getValue().equals("") || buyerAddPhone1ValElement.getValue().equals(null)){
				buyerAddPhone1Element.setText( fixedDataBundle.getString("Buyer.Address.Phone1"));
			} else {
				buyerAddPhone1Element.setText( buyerAddPhone1ValElement.getValue() );
			}
		}
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createBuyerAddress()");
		
	}
	
	private void createRequestDueData() {
		
		
	}
	
	private void createCurrencyCode() {
		
		
	}
	
	private void createStoreInfo() {
		
		
	}
	
	
	/**
	 * createOrderInfo
	 * 
	 * @param efiRootNode
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of Order Id info in EFI xml
	 * 
	 * */
	private void createOrderInfo(Element root, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createOrderInfo()");
		
		Element orderIdDataIdElement = (Element) XPath.newInstance(efiBundle.getString("Order.IdData.External.Id")).selectSingleNode(root);
		Element orderIdDataIdValElement = (Element) XPath.newInstance(canonicalBundle.getString("Order.IdData.External.Id")).selectSingleNode(canonicalRoot);
		if(orderIdDataIdValElement == null){
			throw new Exception("Order number "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderIdDataIdElement.setText( orderIdDataIdValElement.getValue() );
		}
		
		Element orderIdDataIdTypeNameElement = (Element) XPath.newInstance(efiBundle.getString("Order.IdData.External.IdTypeName")).selectSingleNode(root);
		orderIdDataIdTypeNameElement.setText( fixedDataBundle.getString("Order.IdData.External.IdTypeName") );	
		
		Element orderIdDataDescriptionElement = (Element) XPath.newInstance(efiBundle.getString("Order.IdData.External.Description")).selectSingleNode(root);
		orderIdDataDescriptionElement.setText( fixedDataBundle.getString("Order.IdData.External.Description") );
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createOrderInfo()");
		
	}
	
	
	/**
	 * parseLineLevelDataAndPopulateEFI
	 * 
	 * @param vendor
	 * @param lineList
	 * @param efiRoot
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of product info in EFI xml parsing each
	 * line item in canonical xml
	 * 
	 * */
	private void parseLineLevelDataAndPopulateEFI(String vendor, List lineList, Element responseRoot, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.parseLineLevelDataAndPopulateEFI()");
		
		int lineCount=0;
		Element products = (Element)XPath.newInstance("//s1:Order/s1:Products").selectSingleNode(responseRoot);
		Element productTemplate = (Element)XPath.newInstance("//s1:Product").selectSingleNode(products);
		products.removeContent();
		VendorProduct vp = null;
		
		for(int i=0; i<lineList.size(); i++){
			lineCount=lineCount+1;
			
			Element line = (Element) lineList.get(i);
			XPath vendorProdPath = XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+efiBundle.getString("vendorProductPath"));
			Element vendorProdElement = (Element) vendorProdPath.selectSingleNode(canonicalRoot);
			String vendorProduct=vendorProdElement.getValue();
			logger.info("-----> vendorProduct:"+vendorProduct); 
			 
			vp = vendorProductRepository.findByVendorAndProduct(vendor, vendorProduct);
			
			if(vp==null){
				throw new Exception("No vendorproduct is present in DB for this order.");
			}
			
			// Create Product
			createProductDataForEachLineItem(canonicalRoot, products, productTemplate.clone(),lineCount,vp);
			
		}
		
		createBuyerCompanyData(responseRoot,vp);
		
		createThirdPartyCoupons(responseRoot,vp);
		
		logger.info("Leaving CreateEfiXmlServiceImpl.parseLineLevelDataAndPopulateEFI()");
		
	}
	
	/**
	 * createOrderLevelTotalAndTax
	 * 
	 * @param efiRoot
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of Order level total and tax in EFI xml 
	 * 
	 * */
	private void createOrderLevelTotalAndTax(Element root, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createOrderLevelTotalAndTax()");
		
		Element orderLevelDataRequiresManualQuoteElement = (Element) XPath.newInstance(efiBundle.getString("Order.LevelData.TotalsAndTaxes.RequiresManualQuote")).selectSingleNode(root);
		orderLevelDataRequiresManualQuoteElement.setText( fixedDataBundle.getString("Order.LevelData.TotalsAndTaxes.RequiresManualQuote") );
		
		Element orderLevelDataSubtotalElement = (Element) XPath.newInstance(efiBundle.getString("Order.LevelData.TotalsAndTaxes.Subtotal")).selectSingleNode(root);
		Attribute orderLevelDataSubtotalValElement = (Attribute) XPath.newInstance(canonicalBundle.getString("Order.LevelData.TotalsAndTaxes.Subtotal")).selectSingleNode(canonicalRoot);
		if(orderLevelDataSubtotalValElement == null){
			throw new Exception("Overall/Amount "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderLevelDataSubtotalElement.setText( orderLevelDataSubtotalValElement.getValue() );
		}
		
		Element orderLevelDataDiscountElement = (Element) XPath.newInstance(efiBundle.getString("Order.LevelData.TotalsAndTaxes.Discount")).selectSingleNode(root);
		orderLevelDataDiscountElement.setText( fixedDataBundle.getString("Order.LevelData.TotalsAndTaxes.Discount") );
		
		Element orderLevelDataTaxElement = (Element) XPath.newInstance(efiBundle.getString("Order.LevelData.TotalsAndTaxes.Tax")).selectSingleNode(root);
		orderLevelDataTaxElement.setText( fixedDataBundle.getString("Order.LevelData.TotalsAndTaxes.Tax") );
		
		Element orderLevelDataTotalElement = (Element) XPath.newInstance(efiBundle.getString("Order.LevelData.TotalsAndTaxes.Total")).selectSingleNode(root);
		Attribute orderLevelDataTotalValElement = (Attribute) XPath.newInstance(canonicalBundle.getString("Order.LevelData.TotalsAndTaxes.Total")).selectSingleNode(canonicalRoot);
		if(orderLevelDataTotalValElement == null){
			throw new Exception("Overall/Amount "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderLevelDataTotalElement.setText( orderLevelDataTotalValElement.getValue() );
		}
		
		Element resourceEle = (Element)XPath.newInstance("//s1:Order/s1:LevelData/s1:Resources/s1:Resource").selectSingleNode(root);
		resourceEle.getAttribute("type").setNamespace(Namespace.getNamespace("d5p1", "http://www.w3.org/2001/XMLSchema-instance"));
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createOrderLevelTotalAndTax()");
	}
	
	
	/**
	 * createProductDataForEachLineItem
	 * 
	 * @param canonicalRoot
	 * @param products
	 * @param productTemplate
	 * @param lineCount
	 * @param vendorProduct
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of product data in EFI xml 
	 * 
	 * */
	private void createProductDataForEachLineItem(Element canonicalRoot, Element products, Element productTemplate, int lineCount, VendorProduct vp) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createProductDataForEachLineItem()");
		
		products.addContent(productTemplate);
		
		// FOR PRODUCT IdDATA
		Element orderProductIdElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("Order.Products.Product.IdData.External.Id")).selectSingleNode(products);
        Element orderProductHeaderIdValElement = (Element) XPath.newInstance(canonicalBundle.getString("Order.IdData.External.Id")).selectSingleNode(canonicalRoot);

        Element orderProductLineIdValElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("Order.Products.Product.IdData.External.Id")).selectSingleNode(canonicalRoot);
        if(orderProductLineIdValElement == null){
			throw new Exception("Line/Nmb "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderProductIdElement.setText( orderProductHeaderIdValElement.getValue() + orderProductLineIdValElement.getValue() );
		}
        
        logger.info("====>"+orderProductIdElement.getValue());
        
        Element orderProductTypeElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("Order.Products.Product.IdData.External.IdTypeName")).selectSingleNode(productTemplate);
        orderProductTypeElement.setText( fixedDataBundle.getString("Order.Products.Product.IdData.External.IdTypeName") );
        logger.info("====>"+orderProductTypeElement.getValue());
        
        Element orderProductDescElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("Order.Products.Product.IdData.External.Description")).selectSingleNode(productTemplate);
        Element orderProductDescValElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("Order.Products.Product.IdData.External.Description")).selectSingleNode(canonicalRoot);
        if(orderProductDescValElement == null){
			throw new Exception("Ordered/Description "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderProductDescElement.setText( orderProductDescValElement.getValue() );
		}
        
        createProductLevelTotalAndTaxes(canonicalRoot,products,lineCount);
        
        Element resource = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductLevelData.Resources")).selectSingleNode(products);
        createProductPOSData(resource,canonicalRoot,vp,lineCount);
        
        createProductItemData(products, canonicalRoot, lineCount, vp);
        
        logger.info("Leaving CreateEfiXmlServiceImpl.createProductDataForEachLineItem()");
	}
	
	private void createProductLevelData() {
		
		
	}
	
	/**
	 * createProductLevelTotalAndTaxes
	 * 
	 * @param canonicalRoot
	 * @param products
	 * @param lineCount
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of ProductLevelTotalAndTaxes in EFI xml 
	 * 
	 * */
	private void createProductLevelTotalAndTaxes(Element canonicalRoot, Element products, int lineCount) throws Exception {
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createProductLevelTotalAndTaxes()");
		Element orderProductsLevelDataRequiresManualQuoteElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductLevelData.RequiresManualQuote")).selectSingleNode(products);
		orderProductsLevelDataRequiresManualQuoteElement.setText( fixedDataBundle.getString("Order.Products.Product.LevelData.RequiresManualQuote") );
		
		Element orderProductsLevelDataSubtotalElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductLevelData.Subtotal")).selectSingleNode(products);
		Attribute orderProductsLevelDataSubtotalValElement = (Attribute) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("Order.Products.Product.LevelData.Subtotal")).selectSingleNode(canonicalRoot);
		if(orderProductsLevelDataSubtotalValElement == null){
			throw new Exception("Extended/Amount "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderProductsLevelDataSubtotalElement.setText( orderProductsLevelDataSubtotalValElement.getValue() );
		}
		
		Element orderProductsLevelDataDiscountElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductLevelData.Discount")).selectSingleNode(products);
		orderProductsLevelDataDiscountElement.setText( fixedDataBundle.getString("Order.Products.Product.LevelData.Discount") );
		
		Element orderProductsLevelDataTaxElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductLevelData.Tax")).selectSingleNode(products);
		orderProductsLevelDataTaxElement.setText( fixedDataBundle.getString("Order.Products.Product.LevelData.Tax") );
		
		Element orderProductsLevelDataTotalElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductLevelData.Total")).selectSingleNode(products);
		Attribute orderProductsLevelDataTotalValElement = (Attribute) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("Order.Products.Product.LevelData.Total")).selectSingleNode(canonicalRoot);
		if(orderProductsLevelDataTotalValElement == null){
			throw new Exception("Extended/Amount "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			orderProductsLevelDataTotalElement.setText( orderProductsLevelDataTotalValElement.getValue() );
		}
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createProductLevelTotalAndTaxes()");
	}
	
	private void createProductLeveExternalPricing() {
		
	}
	
	
	/**
	 * createProductPOSData
	 * 
	 * @param resource
	 * @param canonicalRoot
	 * @param VendorProduct
	 * @param lineCount
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of ProductPOSData in EFI xml 
	 * 
	 * */
	private void createProductPOSData(Element resource, Element canonicalRoot, VendorProduct vp,int lineCount) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createProductPOSData()");
		
		Set<VendorTemplateSkus> SkuList = vp.getSkus();
		Iterator<VendorTemplateSkus> it  = SkuList.iterator();
		VendorTemplateSkus vtSku =null;
		while(it.hasNext()){
			VendorTemplateSkus eachSku = it.next();
			if(eachSku.getSkuType().getUsgae().equals("POS")){
				vtSku = eachSku;
				break;
			}
		}
		
		if(vtSku == null){
			throw new Exception("POS SKU "+efiBundle.getString("DBNullValueMessage"));
		}
		
		resource.getAttribute("type").setNamespace(Namespace.getNamespace("d10p1", "http://www.w3.org/2001/XMLSchema-instance"));
		Element extPricingData = new Element("ExternalPricingData","s1","com.printcafe.printersiteinternal");
		resource.addContent(extPricingData);
		Element posData = new Element("POSData", "s1", "com.printcafe.printersiteinternal");
		extPricingData.addContent(posData);
		posData.setAttribute(new Attribute("SKU", vtSku.getSku()));
		posData.setAttribute(new Attribute("Description", vtSku.getSkuDescription()));
		Element POSDataQuantityElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("ExternalTicketData.TicketServerInfo.RequestedQuantity")).selectSingleNode(canonicalRoot);
		
		if(POSDataQuantityElement == null){
			throw new Exception("Additional/Quantity "+efiBundle.getString("NullPointerErrorMessage"));
		} else {
			posData.setAttribute(new Attribute("Quantity", "1"));//POSDataQuantityElement.getValue()));
			posData.setAttribute(new Attribute("UnitPrice", vtSku.getPrice().toString()));
		}
		
		Attribute priceAtb = (Attribute) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("Order.Products.Product.LevelData.Total")).selectSingleNode(canonicalRoot);
		if(priceAtb == null){
			throw new Exception("Extended/Amount "+efiBundle.getString("NullPointerErrorMessage"));
		}
		posData.setAttribute(new Attribute("Price", priceAtb.getValue()));
		
		if(vp.getVendorJdfTemplate().getEfiTransform() == null){
			throw new Exception("EFI Transform data "+efiBundle.getString("DBNullValueMessage"));	
		}
		
		String paceIntegration = vp.getVendorJdfTemplate().getEfiTransform().getPaceIntegration();
		if(paceIntegration == null){
			throw new Exception("Pace Integration State "+efiBundle.getString("DBNullValueMessage"));	
		}
		String[] nodeArr= paceIntegration.split("/>");
		for(int i=0; i<nodeArr.length;i++){
			Element doc= null;
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			String nodeStr = nodeArr[i]+"/>";
			org.w3c.dom.Document document = builder.parse(new InputSource(new ByteArrayInputStream(nodeStr.getBytes("utf-8")))) ;
			doc = new DOMBuilder().build(document.getDocumentElement());
			
			// add pace integration data
			extPricingData.addContent(doc.clone().setNamespace(Namespace.getNamespace("s1", "com.printcafe.printersiteinternal")));
		}
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createProductPOSData()");
		
	}
	
	private void createProductResourceHeaderData() {
		
	}
	
	/**
	 * createProductItemData
	 * 
	 * @param productsNode
	 * @param canonicalRoot
	 * @param lineCount
	 * @param VendorProduct
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of ProductItemData in EFI xml 
	 * 
	 * */
	private void createProductItemData(Element products, Element canonicalRoot, int lineCount, VendorProduct vp) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createProductItemData()");
		createItemIdData(products,canonicalRoot,vp,lineCount);
		
		Element resourceEle = (Element)XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+"/s1:ProductData/s1:Items/s1:Item/s1:LevelData/s1:Resources/s1:Resource").selectSingleNode(products);
		resourceEle.getAttribute("type").setNamespace(Namespace.getNamespace("d10p1", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element resourceEle2 = (Element)XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+"/s1:ProductData/s1:Items/s1:Item/s1:LevelData/s1:Resources/s1:Resource[2]").selectSingleNode(products);
		resourceEle2.getAttribute("type").setNamespace(Namespace.getNamespace("d10p1", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element ticketServerInfo = (Element)XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("TicketServerInfo")).selectSingleNode(products);
		Element stateEle = (Element)XPath.newInstance("s2:States/s2:State").selectSingleNode(ticketServerInfo);
		stateEle.getAttribute("type").setNamespace(Namespace.getNamespace("d10p1", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element quantity = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("ExternalTicketData.TicketServerInfo.RequestedQuantity")).selectSingleNode(canonicalRoot);
		if(quantity == null){
			throw new Exception("Additional/Quantity "+efiBundle.getString("NullPointerErrorMessage"));
		}
		
		Element jobName = (Element) XPath.newInstance(canonicalBundle.getString("ExternalTicketData.TicketServerInfo.RequestedJobName")).selectSingleNode(canonicalRoot);
		if(jobName == null){
			throw new Exception("Customer/Nmb "+efiBundle.getString("NullPointerErrorMessage"));
		}
		
		Element pgNoElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("ExternalTicketData.TicketServerInfo.RequestedPageCount")).selectSingleNode(canonicalRoot);
        if(pgNoElement == null){
			throw new Exception("DimensionList/Quantity "+efiBundle.getString("NullPointerErrorMessage"));
		}
        
        int reqPageCount = Integer.parseInt(quantity.getValue())*Integer.parseInt( pgNoElement.getValue());
		
		ticketServerInfo.getAttribute("RequestedQuantity").setValue(quantity.getValue());
		ticketServerInfo.getAttribute("RequestedJobName").setValue(vp.getProductDescription()+", Vendor Order#:"+jobName.getValue());
		ticketServerInfo.setAttribute(new Attribute("RequestedPageCount", pgNoElement.getValue())); 
		
		Element canFileName = (Element)XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("TicketServerInfo.States.State.File.FileName")).selectSingleNode(canonicalRoot);
		if(canFileName == null){
			throw new Exception("ImageURL "+efiBundle.getString("NullPointerErrorMessage"));
		}
		String fileType = fixedDataBundle.getString("TicketServerInfo.States.State.File.FileType.Off");
		
		Element pageCount = (Element)XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("TicketServerInfo.States.State.File.PageCount")).selectSingleNode(canonicalRoot);
		if(pageCount == null){
			throw new Exception("DimensionList/Quantity "+efiBundle.getString("NullPointerErrorMessage"));
		}
		
		Element file = (Element)XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("TicketServerInfo")+"[1]"+efiBundle.getString("TicketServerInfo.States.State.File")).selectSingleNode(ticketServerInfo);
		file.getAttribute("FileName").setValue(canFileName.getValue());
		file.getAttribute("DownloadUrl").setValue(canFileName.getValue());
		file.getAttribute("FileType").setValue(fileType);
		file.getAttribute("PageCount").setValue(pageCount.getValue());
		file.getAttribute("ClassifiedAsNativeFileUpload").setValue(fixedDataBundle.getString("TicketServerInfo.States.State.File.ClassifiedAsNativeFileUpload"));
		file.getAttribute("UploadMethod").setValue(fixedDataBundle.getString("TicketServerInfo.States.State.File.UploadMethod"));
		SimpleDateFormat formatter = new SimpleDateFormat();
		formatter.applyPattern("MM/dd/yyyy HH:mm:ss a z");
		file.getAttribute("SavedOnDateTimeAsDisplayText").setValue(formatter.format(new Date()).toString());
		//file.getAttribute("ExpirationTimeAsDisplayText").setValue("");
		file.getAttribute("OfflineFileSubtype").setValue(fixedDataBundle.getString("TicketServerInfo.States.State.File.OfflineFileSubtype"));
		
		if(vp.getVendorJdfTemplate().getEfiTransform().getTicketDataState()==null){
			throw new Exception("Ticket Data State "+efiBundle.getString("DBNullValueMessage"));
        }
		createProductTicketDataState(products, vp.getVendorJdfTemplate().getEfiTransform().getTicketDataState(),lineCount, canFileName);
		
		Element itemDataCatalogElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+"/s1:ProductData/s1:Items/s1:Item/s1:ItemData/s1:CatalogItem").selectSingleNode(products);
		itemDataCatalogElement.getAttribute("type").setNamespace(Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element productDataCatalogElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+"/s1:ProductData/s1:CatalogItem").selectSingleNode(products);
		productDataCatalogElement.getAttribute("type").setNamespace(Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element itemDataDSFIdElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.CatalogItem.IdData.DSF.Id")).selectSingleNode(products);
		if(vp.getVendorJdfTemplate().getEfiProductId()==null){
			throw new Exception("Efi Product Id "+efiBundle.getString("DBNullValueMessage"));
        }
		itemDataDSFIdElement.setText(Integer.toString(vp.getVendorJdfTemplate().getEfiProductId()));
		
		Element itemTypeElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.CatalogItem.IdData.DSF.IdTypeName")).selectSingleNode(products);
        itemTypeElement.setText( fixedDataBundle.getString("ProductData.Items.Item.ItemData.CatalogItem.IdData.DSF.IdTypeName") );


        Element itemDescElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.CatalogItem.IdData.DSF.Description")).selectSingleNode(products);
        itemDescElement.setText( fixedDataBundle.getString("Order.Products.Product.ProductData.Items.Item.ItemData.CatalogItem.IdData.DSF.Description") );
        
        Element itemDataQuantityElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.DataQuantity")).selectSingleNode(products);
        Element additionalQuantityElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("ProductData.Items.Item.ItemData.Quantity")).selectSingleNode(canonicalRoot);
        if(additionalQuantityElement == null){
			throw new Exception("Additional/Quantity "+efiBundle.getString("NullPointerErrorMessage"));
		}
        itemDataQuantityElement.setText(additionalQuantityElement.getValue() );
		
        Element isPrintedItemElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.IsPrintedItem")).selectSingleNode(products);
        isPrintedItemElement.setText( fixedDataBundle.getString("Order.Products.Product.ProductData.Items.Item.ItemData.IsPrintedItem") );

        Element productClassificationElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.ProductClassification")).selectSingleNode(products);
        productClassificationElement.setText( fixedDataBundle.getString("ProductData.ProductClassification") );      
        
		createItemFileInfo(products,canonicalRoot,lineCount);
		createItemDesc(products,vp, lineCount);
		
		Element productDataQuantityElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+"/s1:ProductData/s1:Quantity").selectSingleNode(products);
		productDataQuantityElement.setText(quantity.getValue());
		logger.info("Leaving CreateEfiXmlServiceImpl.createProductItemData()");
		
	}

	private void createProductTicketDataState(Element products, String ticketDataState,int lineCount, Element canFileName) throws Exception {
			
		logger.info("Entering CreateEfiXmlServiceImpl.createProductTicketDataState()");
		Element state = (Element)XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.LevelData.TicketData.TicketServerInfo.States.State")).selectSingleNode(products);
		
		String[] nodeArr= ticketDataState.split("/>");
		for(int i=0; i<nodeArr.length;i++){
			
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			String nodeStr = nodeArr[i]+"/>";
			nodeStr = nodeStr.replace("btcs:", "s2:");
			org.w3c.dom.Document document = builder.parse(new InputSource(new ByteArrayInputStream(nodeStr.getBytes("utf-8")))) ;
			Element doc= new DOMBuilder().build(document.getDocumentElement());
			doc.getAttribute("type").setNamespace(Namespace.getNamespace("d10p1", "http://www.w3.org/2001/XMLSchema-instance"));
			
			state.addContent(doc.clone().setNamespace(Namespace.getNamespace("s2", "http://www.efi.com/dsf/BuyerTicketClientServices")));
		}
		
		createProductTicketDataOperNotes(products,state,canFileName);
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createProductTicketDataState()");
	}
	
	private void createProductTicketDataStateForFiles() {
			
		
	}

	/**
	 * createProductTicketDataOperNotes
	 * 
	 * @param productsNode
	 * @param stateNode
	 * @param fileName
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of ProductTicketDataOperNotes in EFI xml 
	 * 
	 * */
	private void createProductTicketDataOperNotes(Element products, Element state, Element canFileName)throws Exception {
		logger.info("Entering CreateEfiXmlServiceImpl.createProductTicketDataOperNotes()");
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		String nodeStr = "<btcs:State d10p1:type=\"s2:TicketStateForOperatorNotes\" Notes=\"\"/>";
		org.w3c.dom.Document document = builder.parse(new InputSource(new ByteArrayInputStream(nodeStr.getBytes("utf-8")))) ;
		Element doc= new DOMBuilder().build(document.getDocumentElement());
		doc.getAttribute("type").setNamespace(Namespace.getNamespace("d10p1", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element operNotes = doc.clone().setNamespace(Namespace.getNamespace("s2", "http://www.efi.com/dsf/BuyerTicketClientServices"));
		operNotes.setAttribute("Notes", canFileName.getValue());
		
		state.addContent(operNotes);
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createProductTicketDataOperNotes()");
	}
	
	private void createStaplesResourceHeader() {
		
		
	}
	
	/**
	 * createItemIdData
	 * 
	 * @param productsNode
	 * @param canonicalRoot
	 * @param vendorProduct
	 * @param lineCount
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of product ItemIdData in EFI xml 
	 * 
	 * */
	private void createItemIdData(Element products, Element canonicalRoot, VendorProduct vp, int lineCount) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createItemIdData()");
		Element orderProductsProductDataIdElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.IdData.External.Id")).selectSingleNode(products);
		//Element orderProductsProductDataIdValElement1 = (Element) XPath.newInstance(canonicalBundle.getString("Order.IdData.External.Id")).selectSingleNode(canonicalRoot);
		//Element orderProductsProductDataIdValElement2 = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("Order.Products.Product.IdData.External.Id")).selectSingleNode(canonicalRoot);
		orderProductsProductDataIdElement.setText("20201");
		
		Element orderProductsProductDataIdTypeNameElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.IdData.External.IdTypeName")).selectSingleNode(products);
		orderProductsProductDataIdTypeNameElement.setText( fixedDataBundle.getString("Order.Products.Product.ProductData.Items.Item.IdData.External.IdTypeName") );
		
		Element orderProductsProductDataDescriptionElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.IdData.External.Description")).selectSingleNode(products);
		Attribute vendorOrderAtb = (Attribute) XPath.newInstance(canonicalBundle.getString("ProductData.Items.Item.IdData.Description")).selectSingleNode(canonicalRoot);
		if(vendorOrderAtb == null){
			throw new Exception("Original "+efiBundle.getString("NullPointerErrorMessage"));
		}
		orderProductsProductDataDescriptionElement.setText( vp.getProductDescription()+", Vendor Order#:"+vendorOrderAtb.getValue());
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createItemIdData()");
	}
	
	/**
	 * createItemFileInfo
	 * 
	 * @param productsNode
	 * @param canonicalRoot
	 * @param lineCount
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of product ItemFileInfo in EFI xml 
	 * 
	 * */
	private void createItemFileInfo(Element products,Element canonicalRoot, int lineCount) throws Exception  {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createItemFileInfo()");
		
		Element itenDataFilenameElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.Files.File.Filename")).selectSingleNode(products);
        Element imageUrlElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("ProductData.Items.Item.ItemData.ImageURL")).selectSingleNode(canonicalRoot);
        if(imageUrlElement == null){
			throw new Exception("ImageUrl "+efiBundle.getString("NullPointerErrorMessage"));
		}
        itenDataFilenameElement.setText(imageUrlElement.getValue() );
        
        Element itemDataFileImpressionsElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.Files.File.Impressions")).selectSingleNode(products);
        Element dimensionQuantityElement = (Element) XPath.newInstance(efiBundle.getString("lineNodePath")+"["+lineCount+"]"+canonicalBundle.getString("ExternalTicketData.TicketServerInfo.RequestedPageCount")).selectSingleNode(canonicalRoot);
        if(dimensionQuantityElement == null){
			throw new Exception("Unit/Quantity "+efiBundle.getString("NullPointerErrorMessage"));
		}
        itemDataFileImpressionsElement.setText(dimensionQuantityElement.getValue() );
        
        logger.info("Leaving CreateEfiXmlServiceImpl.createItemFileInfo()");
	}
	
	
	/**
	 * createItemDesc
	 * 
	 * @param productsNode
	 * @param VendorProduct
	 * @param lineCount
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of product ItemDesc in EFI xml 
	 * 
	 * */
	private void createItemDesc(Element products,VendorProduct vp, int lineCount) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createItemDesc()");
		
		Element itemDataItemDescriptionElement = (Element) XPath.newInstance(efiBundle.getString("Product")+"["+lineCount+"]"+efiBundle.getString("ProductData.Items.Item.ItemData.ItemDescription")).selectSingleNode(products);
		if(vp.getProductDescription()==null){
			throw new Exception("Product Description "+efiBundle.getString("DBNullValueMessage"));
        }
		itemDataItemDescriptionElement.setText(vp.getProductDescription());
        
        logger.info("Leaving CreateEfiXmlServiceImpl.createItemDesc()");
	}
	
	private void createProductClassificationAndQty() {
		
		
	}
	
	private void createShippingAddressAndMethod() {
		
		
	}
	
	private void createMultipleShipmentOrderFlag() {
		
		
	}
	
	/**
	 * createPaymentMethodAndPaymentAddress
	 * 
	 * @param efiroot
	 * @param canonicalRoot
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of product ItemDesc in EFI xml 
	 * 
	 * */
	private void createPaymentMethodAndPaymentAddress(Element root, Element canonicalRoot) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createPaymentMethodAndPaymentAddress()");
		
		Element paymentMethod = (Element) XPath.newInstance("//s1:Payment/s1:PaymentMethod").selectSingleNode(root);
		paymentMethod.getAttribute("type").setNamespace(Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element paymentMethodIdElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentMethod.IdData.DSF.Id")).selectSingleNode(root);
		paymentMethodIdElement.setText( fixedDataBundle.getString("Payment.PaymentMethod.IdData.DSF.Id") );
		
		Element paymentMethodIdTypeNameElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentMethod.IdData.DSF.IdTypeName")).selectSingleNode(root);
		paymentMethodIdTypeNameElement.setText( fixedDataBundle.getString("Payment.PaymentMethod.IdData.DSF.IdTypeName") );
		
		Element paymentMethodDescNameElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentMethod.IdData.DSF.Description")).selectSingleNode(root);
		paymentMethodDescNameElement.setText( fixedDataBundle.getString("Payment.PaymentMethod.IdData.DSF.Description") );
		
		Element paymentAddressFirstNameElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentAddress.NameFirst")).selectSingleNode(root);
		Element paymentAddressFirstNameValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.User.NameComponents.First")).selectSingleNode(canonicalRoot);
		paymentAddressFirstNameElement.setText( paymentAddressFirstNameValElement.getValue() );
	     
		Element paymentAddressLastNameElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentAddress.NameLast")).selectSingleNode(root);
		Element paymentAddressLastNameValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.User.NameComponents.Last")).selectSingleNode(canonicalRoot);
		paymentAddressLastNameElement.setText( paymentAddressLastNameValElement.getValue() );
		
		Element paymentAddressCityElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentAddress.City")).selectSingleNode(root);
		Element paymentAddressCityValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.City")).selectSingleNode(canonicalRoot);
		paymentAddressCityElement.setText( paymentAddressCityValElement.getValue() );
	     
		Element paymentAddressStateElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentAddress.State_Province_Region")).selectSingleNode(root);
		Element paymentAddressStateValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.State_Province_Region")).selectSingleNode(canonicalRoot);
		paymentAddressStateElement.setText( paymentAddressStateValElement.getValue() );
	     
		Element paymentAddressZipElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentAddress.Zip_PostalCode")).selectSingleNode(root);
		Element paymentAddressZipValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.Zip_PostalCode")).selectSingleNode(canonicalRoot);
		paymentAddressZipElement.setText( paymentAddressZipValElement.getValue() );
		
		Element paymentAddressCountryElement = (Element) XPath.newInstance(efiBundle.getString("Payment.PaymentAddress.Country")).selectSingleNode(root);
		//Element paymentAddressCountryValElement = (Element) XPath.newInstance(canonicalBundle.getString("Buyer.Address.Country")).selectSingleNode(canonicalRoot);
		paymentAddressCountryElement.setText( "US" );
	     
		Element paymentAddress = (Element) XPath.newInstance(efiBundle.getString("Payment.ProcessedByDSF")).selectSingleNode(root);
		paymentAddress.setText( fixedDataBundle.getString("Payment.ProcessedByDSF") );
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createPaymentMethodAndPaymentAddress()");
	}
	
	private void createProcessedByDSF() {
		
		
	}
	
	/**
	 * createThirdPartyCoupons
	 * 
	 * @param efiroot
	 * @param VendorProduct
	 * @throws Exception 
	 * 
	 * This method is responsible for population
	 * of ThirdPartyCoupons info in EFI xml 
	 * 
	 * */
	private void createThirdPartyCoupons(Element efiRoot, VendorProduct vp) throws Exception {
		
		logger.info("Entering CreateEfiXmlServiceImpl.createThirdPartyCoupons()");
		
		Set<VendorTemplateSkus> SkuList = vp.getSkus();
		Iterator<VendorTemplateSkus> it  = SkuList.iterator();
		VendorTemplateSkus vtSku =null;
		while(it.hasNext()){
			VendorTemplateSkus eachSku = it.next();
			if(eachSku.getSkuType().getUsgae().equals("Coupon")){
				vtSku = eachSku;
				break;
			} 
		}
		if(vtSku == null){
			throw new Exception("Coupon SKU "+efiBundle.getString("DBNullValueMessage"));
		}
		
		Element paymentMethod = (Element) XPath.newInstance("//s1:ThirdPartyCoupons/s1:ThirdPartyCoupon/s1:ThirdPartyCouponId").selectSingleNode(efiRoot);
		paymentMethod.getAttribute("type").setNamespace(Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
		
		Element couponExtIdElement = (Element) XPath.newInstance(efiBundle.getString("ThirdPartyCoupons.ThirdPartyCoupon.ThirdPartyCouponId.IdData.External.Id")).selectSingleNode(efiRoot);
		couponExtIdElement.setText( vtSku.getSku() );
		
		Element couponExtTypeNameElement = (Element) XPath.newInstance(efiBundle.getString("ThirdPartyCoupons.ThirdPartyCoupon.ThirdPartyCouponId.IdData.External.IdTypeName")).selectSingleNode(efiRoot);
		couponExtTypeNameElement.setText( "Third Party Coupon" );
		
		Element couponExtDescElement = (Element) XPath.newInstance(efiBundle.getString("ThirdPartyCoupons.ThirdPartyCoupon.ThirdPartyCouponId.IdData.External.Description")).selectSingleNode(efiRoot);
		couponExtDescElement.setText( vtSku.getSkuDescription() );
		
		logger.info("Leaving CreateEfiXmlServiceImpl.createThirdPartyCoupons()");
		
	}
}
